/**
 * @file pt_pcm_utils.c
 * @brief pcm 数据处理工具
 * @author yejiahao
 * @date 2024-06-24 02:16:24
 * 
 * @copyright Copyright (c) 2024 by 深圳市鹏天微智能科技有限公司, All Rights Reserved.
 */

#include "pt_pcm_utils.h"

long pt_get_bin_size(const char *read_file)
{
    FILE *file = fopen(read_file, "rb");
    if (file == NULL)
    {
        PT_LOGE("fopen file failed!\n");
        return 0;
    }

    fseek(file, 0, SEEK_END);
    long total_size = ftell(file);
    rewind(file);

    fclose(file);

    PT_LOGD("size=%ld\n", total_size);
    return total_size;
}

int pt_read_pcm(const char *read_file, uint8_t **pcm)
{
    FILE *file = fopen(read_file, "rb");
    if (file == NULL)
    {
        PT_LOGE("fopen file failed!\n");
        return -1;
    }

    fseek(file, 0, SEEK_END);
    long pcm_size = ftell(file);
    rewind(file);
    PT_LOGD("pcm size=%ld\n", pcm_size);

    uint8_t *buffer = malloc(pcm_size);
    if (!buffer)
    {
        fclose(file);
        return -2;
    }

    // 读取文件内容到缓冲区
    size_t result = fread(buffer, 1, pcm_size, file);
    if (result != pcm_size) {
        free(buffer);
        fclose(file);
        return -3;
    }

    fclose(file);
    *pcm = buffer;

    return pcm_size;
}

int pt_save_pcm(const char *save_path, void *buffer, size_t len)
{
    FILE * file = fopen(save_path, "wb");
    if (file == NULL)
    {
        PT_LOGE("fopen file failed!\n");
        return 1;
    }

    // 将数据写入文件
    size_t written = fwrite(buffer, 1, len, file);
    if (written != len) {
        PT_LOGE("written error!\n");
        fclose(file);
        return EXIT_FAILURE;
    }

    // 关闭文件
    fclose(file);
    PT_LOGI("write success!\n");

    return 0;
}

/**
 * @brief 双声道转换单声道
 * 
 * @param[in] stereo 双声道音频数据
 * @param[in] stereo_frames 双声道音频数据帧数
 * @param[in] mono 单声道音频数据buffer
 * @param[in] mono_frames 单声道音频数据buffer帧数
 */
void pt_stereo2mono(const int16_t *stereo, const uint32_t stereo_frames, int16_t *mono, uint32_t mono_frames)
{
    if (mono_frames != (stereo_frames >> 1))
    {
        PT_LOGW("size mismatch!\n");
        return;
    }

    for (int i = 0; i < mono_frames; i++) 
    {
    	// 注意 >>1 只有在有符号整形的情况下才代表除以2
        // mono[i] = (stereo[2 * i] + stereo[2 * i + 1]) >> 1; /*!< 均值 */
        mono[i] = stereo[2 * i]; /*!< 左声道 */
        // mono[i] = stereo[2 * i + 1]; /*!< 右声道 */
    }
}

/**
 * @brief 单声道转双声道
 * 
 * @param[in] mono 单声道音频数据buffer
 * @param[in] mono_frames 单声道音频数据buffer帧数
 * @param[in] stereo 双声道音频数据
 * @param[in] stereo_frames 双声道音频数据帧数
 */
void pt_mono2stereo(const int16_t *mono, const uint32_t mono_frames, int16_t *stereo, uint32_t stereo_frames) 
{
    if (stereo_frames != (mono_frames << 1))
    {
        PT_LOGW("size mismatch!\n");
        return;
    }

    for (int i = 0; i < mono_frames; i++) 
    {
        stereo[2 * i] = mono[i];
        stereo[2 * i + 1] = mono[i];
    }
}

